"""
Module for reading and writing ini setting unicode files.
"""
import ConfigParser
from ConfigParser import ConfigParser as Base
import os
import codecs

#########################################################
#
#   UniConfig
#
#########################################################
class UniConfig(Base):
    """
    Reference from Koan/setting.py
    support read/write unicode config, should compatible with Win32 API WritePrivateProfileStringW 
    ----------------------------------------------------------
    
    Note, don't save string with special characters such as
    chr(0x09, 0x0b, 0x0c, 0x0d, 0x1a).

    Be careful the special behavior:
      - DEFAULT section
      - value interpolation

    See more detail in the document of ConfigParser module.
    """
    def __init__(self, encode='utf8'):
        """
        Specific the file codec @encode
        """
        Base.__init__(self)
        self.filesrc = ''
        self.path = '.'
        self.encode = encode
    
    def read(self, filename):
        print '[UniConfig] read', filename
        self.filesrc = filename
        self.path = os.path.split(filename)[0]
        try:
            Base.readfp(self, codecs.open(filename, "r", self.encode))
        except:
            print filename, 'not exist'
    
    def sync(self):
        if self.filesrc:
            self.write(codecs.open(self.filesrc, "w", self.encode))
    
    def write(self, fp):
        """
        Override from Python/Lib/ConfigParser.py for write unicode
        Write an .ini-format representation of the configuration state.
        """
        DEFAULTSECT = "DEFAULT"
        if self._defaults:
            fp.write("[%s]\r\n" % DEFAULTSECT)
            for (key, value) in self._defaults.items():
                fp.write("%s = %s\r\n" % (key, value))
            fp.write("\r\n")
        for section in self._sections:
            fp.write("[%s]\r\n" % section)
            for (key, value) in self._sections[section].items():
                if key == "__name__":
                    continue
                if (value is not None) or (self._optcre == self.OPTCRE):
                    v = value
                    key = " = ".join((key, value))
                fp.write("%s\r\n" % (key))
            fp.write("\r\n")
    
    def _2s(self, s):
        if s is None:
            return None
        elif isinstance(s, basestring):
            return s
        return unicode(s)
    
    def get(self, section, option, default=None, raw=False):
        if default is None:
            return Base.get(self, section, option)
        else:
            try:
                return Base.get(self, section, option, raw)
            except ConfigParser.NoSectionError:
                self.set(section, option, default)
            except ConfigParser.NoOptionError:
                self.set(section, option, default)
            return default
    
    def set(self, section, option, value):
        value = self._2s(value)
        try:
            Base.set(self, section, option, value)
        except ConfigParser.NoSectionError:
            self.add_section(section)
            Base.set(self, section, option, value)
    
    def getBool(self, section, option, default=None):
        v = self.get(section, option, default)
        return v.upper() == u'TRUE'
    
    def getInt(self, section, option, default=None):
        v = self.get(section, option, default)
        try:
            return int(v)
        except ValueError:
            if default is not None:
                return default
            else:
                raise
    
    def getFloat(self, section, option, default=None):
        v = self.get(section, option, default)
        try:
            return float(v)
        except ValueError:
            if default is not None:
                return default
            else:
                raise



if __name__=='__main__':
    import os
    now = os.path.split(__file__)[0]
    
    config = UniConfig('utf_16')
    config.read( os.path.join(now, 'test.ini') )
    
    config.set(u'Test', u'unicode', unichr(0x5927) + unichr(0x5BB6) + unichr(0x597D))
    config.set(u'Test', u'ansi',    'test_value\r\n2nd_line')
    config.set(u'Test', u'int',     100)
    config.set(u'Test', u'float',   1.234)
    config.set(u'Test', u'bool',    True)
    config.sync()
    